#include <iostream>
#include <pthread.h>
#include "counterthread.h"

using namespace std;

int startCounterThread(pthread_t* threadId, std::string name, int max, int delay) {
    int ret = 0;

    pthread_attr_t attr;
    pthread_attr_init (&attr);  // Initialize thread-attributes with default values
    ThreadData* threadData = new ThreadData(name, max, delay);  // Initialize data

    if (pthread_create(threadId, &attr, counterThread, threadData) < 0) {
        ret = -1;
    }

    pthread_attr_destroy(&attr);  // Destroy the thread-attributes

    return ret;
}

int joinCounterThread(pthread_t& threadId, int* retValue) {
    int ret = 0;
    void* p_retValue;

    if (pthread_join(threadId, &p_retValue) == 0) {  // Wait for thread 2
        *retValue = *(int*) p_retValue;              // and absorb its return-value
        delete (int*) p_retValue;  // Destroy memory allocated in startCounterThread()
    } else {
        ret = -1;
    }

    return ret;
}

int main(int artc, char* argv[]) {
    pthread_t thread[2];  // We want to create two threads
    int retValue;  // Provide memory for the pointer returned from counterThread()

    if (startCounterThread(&thread[0], "Counter 1:", 20, 300) < 0) {  // Start thread 1
        std::cerr << "Error: Can not start thread 1" << std::endl;
        return -1;
    }
    if (startCounterThread(&thread[1], "Counter 2:", 10, 700) < 0) {  // Start thread 2
        std::cerr << "Error: Can not start thread 2" << std::endl;
        return -1;
    }
    if (joinCounterThread(thread[0], &retValue) < 0) {  // Wait for thread 1
        std::cerr << "Error: Can not join thread 1" << std::endl;
    } else {
        std::cout << "Thread1: Return: " << retValue << std::endl;
    }
    if (joinCounterThread(thread[1], &retValue) < 0) {  // Wait for thread 2
        std::cerr << "Error: Can not join thread 2" << std::endl;
    } else {
        std::cout << "Thread2: Return: " << retValue << std::endl;
    }
    return 0;
}
